package com.ubao.global;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.TimeZone;

import android.text.format.Time;

import com.ubao.util.Drawer;

public class TimeManager {

	private static final String TAG = "KLine";

	private static HashMap<String, String[]> map = null;

	private static boolean hasSetServerTime = false;

	private static long serverDateMillis;// 服务器的年月日的毫秒数

	private static long offsetHMSMillis;// 服务器与本地时分秒相差的毫秒数（不计日期相差）

	private static final String[] CODE = { "HK", "DJIA", "NDX", "SP5I", "TSX",
			"BVSP", "HSI", "HSCEI", "HSAHP", "TWII", "N225", "NHI", "STI",
			"YNI", "MGI", "AUSI", "FCHI", "FTSE", "GDAXI", "AEX", "SSMI",
			"BELI", "UDI", };

	private static final byte[][] DST_DURATION = { null, { 3, 2, 11, 1 },/*
																		 * 3月2日～
																		 * 11
																		 * 月1日
																		 */
	{ 3, 2, 11, 1 }, { 3, 2, 11, 1 }, { 3, 2, 11, 1 }, { 10, 3, 2, 2 }, null,
			null, null, null, null, null, null, null, null, { 10, 1, 4, 1 },
			{ 3, 0, 10, 0 }, { 3, 0, 10, 0 }, { 3, 0, 10, 0 }, { 3, 0, 10, 0 },
			{ 3, 0, 10, 0 }, { 3, 0, 10, 0 }, null, };

	/* 夏令时 */
	private static final String[][] DST_TIMEPOINTS = {
			{ "093000", "120000", "130000", "160000" },
			{ "213000", "235959", "000000", "040000" },
			{ "213000", "235959", "000000", "040000" },
			{ "213000", "235959", "000000", "040000" },
			{ "213000", "235959", "000000", "050000" },
			{ "210000", "235959", "000000", "041000" },
			{ "100000", "123000", "143000", "160000" },
			{ "100000", "123000", "143000", "160000" },
			{ "100000", "123000", "143000", "160000" }, { "090000", "133000" },
			{ "080000", "100000", "113000", "140000" }, { "080000", "140000" },
			{ "090000", "123000", "140000", "170000" },
			{ "103000", "123000", "150000", "175000" }, { "080000", "180000" },
			{ "075000", "130000" }, { "150000", "233000" },
			{ "150000", "233000" }, { "150000", "233000" },
			{ "150000", "235959" }, { "150000", "235959" },
			{ "150000", "235959" }, { "060000", "235959", "000000", "044500" }, };

	/* 冬令时 */
	private static final String[][] NOT_DST_TIMEPOINTS = {
			{ "093000", "120000", "130000", "160000" },
			{ "223000", "235959", "000000", "050000" },
			{ "223000", "235959", "000000", "050000" },
			{ "223000", "235959", "000000", "050000" },
			{ "223000", "235959", "000000", "060000" },
			{ "220000", "235959", "000000", "051000" },
			{ "100000", "123000", "143000", "160000" },
			{ "100000", "123000", "143000", "160000" },
			{ "100000", "123000", "143000", "160000" }, { "090000", "133000" },
			{ "080000", "100000", "113000", "140000" }, { "080000", "140000" },
			{ "090000", "123000", "140000", "170000" },
			{ "103000", "123000", "150000", "175000" }, { "080000", "180000" },
			{ "085000", "140000" }, { "160000", "235959", "000000", "003000" },
			{ "160000", "235959", "000000", "003000" },
			{ "160000", "235959", "000000", "003000" },
			{ "160000", "235959", "000000", "010000" },
			{ "160000", "235959", "000000", "010000" },
			{ "160000", "235959", "000000", "010000" },
			{ "060000", "235959", "000000", "044500" }, };

	private static final String[] NATIONAL_TIMEPOINTS = { "091500", "113000",
			"130000", "151500" };

	/**
	 * 设置服务器时间
	 * 
	 * @param serverDate
	 *            年月日 yyyymmdd
	 * 
	 * @param serverHMS
	 *            时分秒 hhmmss
	 */
	public static void setServerTime(int serverDate, int serverHMS) {
		Time localTime = getLocalTime();

		final int[] time = computeTime(serverDate, serverHMS);
		final int day = time[2];
		final int month = time[1];
		final int year = time[0];
		final int second = time[5];
		final int minute = time[4];
		final int hour = time[3];

		Time serverTime = new Time("Asia/Hong_Kong");
		serverTime.set(day, month - 1, year);
		serverDateMillis = serverTime.toMillis(true);

		serverTime.set(second, minute, hour, localTime.monthDay,
				localTime.month, localTime.year);
		offsetHMSMillis = serverTime.toMillis(true) - localTime.toMillis(true);

		hasSetServerTime = true;
	}

	/** 年月日时分秒 */
	public static int[] computeTime(int date, int hms) {
		final int[] time = new int[6];
		time[0] = date / 10000;
		time[1] = (date / 100) % 100;
		time[2] = date % 100;

		time[3] = hms / 10000;
		time[4] = (hms / 100) % 100;
		time[5] = hms % 100;

		return time;
	}

	/**
	 * 计算前后两个时间之间的周期个数
	 * 
	 * @param cycleLen
	 *            周期长度,单位为毫秒
	 * @param max
	 *            周期个数 <= max
	 * @return 周期个数
	 */
	public static int computeCycleCount(int startTime, int endTime,
			int cycleLen, int max) {
		// 要做相应限制，有时候不需要很大的数据
		String tmp1 = String.format("%08d", startTime);
		String tmp2 = String.format("%08d", endTime);

		if (tmp1.length() != 8)
			tmp1 = Drawer.parseIntToTimeWithYear(startTime) + "00";
		else
			tmp1 += "000000";

		if (tmp2.length() != 8)
			tmp2 = Drawer.parseIntToTimeWithYear(endTime) + "00";
		else
			tmp2 += "000000";

		int[] sTime = computeTime(Integer.valueOf(tmp1.substring(0, 8)),
				Integer.valueOf(tmp1.substring(8)));// 开始年月日时分秒数组
		int[] eTime = computeTime(Integer.valueOf(tmp2.substring(0, 8)),
				Integer.valueOf(tmp2.substring(8)));// 结束年月日时分秒数组

		Time start = new Time("Asia/Hong_Kong");
		Time end = new Time("Asia/Hong_Kong");
		start.set(sTime[5], sTime[4], sTime[3], sTime[2], sTime[1] - 1,
				sTime[0]);
		end.set(eTime[5], eTime[4], eTime[3], eTime[2], eTime[1] - 1, eTime[0]);

		long tmp = (end.toMillis(true) - start.toMillis(true)) / cycleLen + 1;

		return (tmp < max) ? (int) tmp : max;
	}

	/** 返回时间："20101112T102500" */
	public static String getTimeNow() {
		Time time = getLocalTime();
		
		if (hasSetServerTime)
			time.set(time.toMillis(true) + offsetHMSMillis);

		String hms = time.format2445().substring(8);

		if (hasSetServerTime)
			time.set(serverDateMillis);

		return time.format2445().substring(0, 8) + hms;
	}
	
	public static Long getDayInMills(){
		Calendar cal = new GregorianCalendar();
		cal.setTimeInMillis(0);
		Time time = getLocalTime();
		cal.set(cal.YEAR, time.year);
		cal.set(cal.MONTH, time.month);
		cal.set(cal.DAY_OF_MONTH, time.monthDay);
	//	Log.e("aaaaaaa", time.year+" "+ time.month+" "+time.monthDay+" "+cal.getTimeInMillis()+" "+System.currentTimeMillis());
		return cal.getTimeInMillis();
	}

	/** 获取手机上的本地时间（未调整） */
	public static Time getLocalTime() {
		Time time = new Time("Asia/Hong_Kong");
		time.setToNow();

		return time;
	}

	/** 返回时分秒 */
	public static String getHMS() {
		return getTimeNow().substring(9);
	}

	public static String getDate() {
		return getTimeNow().substring(0, 8);
	}

	/** 一周中的第几天，0为星期日 */
	public static int getDay() {
		Calendar calendar = Calendar.getInstance();
		TimeZone t = TimeZone.getTimeZone("Asia/Hong_Kong");
		calendar.setTimeZone(t);
		if (hasSetServerTime)
			calendar.setTimeInMillis(serverDateMillis);
		return calendar.get(Calendar.DAY_OF_WEEK) - 1;
	}

	/**
	 * 计算某年某月第几个星期日的日期
	 * 
	 * @param sundayNum
	 *            第几个星期日 0表示最后一个
	 * 
	 * @return like "20101112"
	 */
	public static String getDate(int year, byte month, byte sundayNum) {
		Calendar c = Calendar.getInstance();
		TimeZone t = TimeZone.getTimeZone("Asia/Hong_Kong");
		c.setTimeZone(t);
		c.set(year, month - 1, 1);

		int day = 0;
		if (sundayNum > 0) {
			int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
			if (dayOfWeek == 0)
				day = 1 + (sundayNum - 1) * 7;
			else
				day = 1 + sundayNum * 7 - dayOfWeek;
		} else {
			day = c.getActualMaximum(Calendar.DAY_OF_MONTH);
			c.set(Calendar.DAY_OF_MONTH, day);
			int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
			day -= dayOfWeek;
		}

		c.set(Calendar.DAY_OF_MONTH, day);

		Time time = new Time("Asia/Hong_Kong");
		time.set(c.get(Calendar.DAY_OF_MONTH), c.get(Calendar.MONTH),
				c.get(Calendar.YEAR));

		return time.format2445().substring(0, 8);
	}

	/** 是否在夏令时期间内 */
	public static boolean isInDst(final int index) {
		Calendar c = Calendar.getInstance();
		TimeZone timeZone = TimeZone.getTimeZone("Asia/Hong_Kong");
		c.setTimeZone(timeZone);
		if (hasSetServerTime)
			c.setTimeInMillis(serverDateMillis);
		int year = c.get(Calendar.YEAR);
		int dateNow = Integer
				.parseInt(TimeManager.getTimeNow().substring(0, 8));
		// Log.v("dst", "now:" + dateNow);

		byte[] t = DST_DURATION[index];
		if (t == null)
			return true;

		if (t[2] < t[0]) {
			if ((dateNow >= Integer.parseInt(TimeManager.getDate(year, t[0],
					t[1])) && dateNow <= Integer.parseInt(String.valueOf(year)
					+ "1231"))
					|| (dateNow >= Integer.parseInt(String.valueOf(year)
							+ "0101") && dateNow <= Integer
							.parseInt(TimeManager.getDate(year, t[2], t[3]))))
				return true;
		} else {
			if (dateNow >= Integer.parseInt(TimeManager.getDate(year, t[0],
					t[1]))
					&& dateNow <= Integer.parseInt(TimeManager.getDate(year,
							t[2], t[3])))
				return true;
		}

		return false;
	}

	public static boolean isRunning(final String[] timePoints) {
		if (timePoints == null) {
			return true;
		}

		int timeNow = Integer.parseInt(getHMS());
		for (int i = 0; i < timePoints.length; i += 2) {
			if (timeNow >= Integer.parseInt(timePoints[i])
					&& timeNow <= Integer.parseInt(timePoints[i + 1])) {
				return true;
			}
		}

		return false;
	}

	/** 用于全球指数 */
	public static boolean isRunning(final String code) {
		int today = getDay();
		if (today == 0
				|| (today == 6 && Integer.parseInt(getHMS().substring(0, 2)) >= 6))
			return false;

		return isRunning(getTimePoint(code));
	}

	/** 用于国内指数 */
	public static boolean isRunning() {
		int today = getDay();
		if (today == 0 || today == 6)
			return false;

		return isRunning(NATIONAL_TIMEPOINTS);
	}

	public static void initMap() {
		synchronized (TimeManager.class) {
			if (map == null) {
				map = new HashMap<String, String[]>();
				for (int i = 0; i < CODE.length; i++) {
					if (isInDst(i)) {
						// Log.v("dst", CODE[i] + " true");
						map.put(CODE[i], DST_TIMEPOINTS[i]);
					} else {
						// Log.v("dst", CODE[i] + " false");
						map.put(CODE[i], NOT_DST_TIMEPOINTS[i]);
					}
				}
			}
		}
	}

	/**
	 * 日期1减去日期2
	 * 
	 * @param d1
	 * @param d2
	 * @return d1 - d2
	 */
	public static int dateDiff(String d1, String d2) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			Date date1 = sdf.parse(d1);
			Date date2 = sdf.parse(d2);
			int dateDiff = (int) ((date1.getTime() - date2.getTime()) / (1000 * 60 * 60 * 24));
			return dateDiff;
		} catch (Exception e) {
			return 0;
		}

	}

	public static String[] getTimePoint(String code) {
		initMap();
		return map.get(code);
	}

	public static void clean() {
		synchronized (TimeManager.class) {
			if (map != null) {
				map.clear();
				map = null;
			}
		}
	}

	public static void init() {
		hasSetServerTime = false;
		offsetHMSMillis = 0;
		serverDateMillis = 0;
	}
}
